/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.enums.IsfdBusinessDatabaseTypeEnum;
import com.comac.ins.isfd.constant.enums.IsfdBusinessScenariosTypeEnum;
import com.comac.ins.isfd.domain.IsfdBusinessScenarios;
import com.comac.ins.isfd.domain.bo.IsfdBusinessScenariosBo;
import com.comac.ins.isfd.domain.bo.query.IsfdBusinessScenariosQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdBusinessScenariosVo;
import com.comac.ins.isfd.mapper.IsfdBusinessScenariosMapper;
import com.comac.ins.isfd.service.IIsfdBusinessScenariosService;
import com.comac.ins.isfd.service.IIsfdDatabaseModelTreeService;
import com.comac.ins.system.domain.vo.SysUserVo;
import com.comac.ins.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 业务场景/系统Service业务层处理
 *
 * @author hxloongs
 * @date 2025-02-27
 */
@RequiredArgsConstructor
@Service
public class IsfdBusinessScenariosServiceImpl implements IIsfdBusinessScenariosService {

    @Autowired
    private IsfdBusinessScenariosMapper baseMapper;

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private IIsfdDatabaseModelTreeService iIsfdDatabaseModelTreeService;

    @Override
    public List<IsfdBusinessScenariosVo> tree(String name) {
        IsfdBusinessScenariosBo bo = new IsfdBusinessScenariosBo();
        bo.setName(name);
        List<IsfdBusinessScenariosVo> allNodes = this.queryList(bo);
        if (CollectionUtils.isEmpty(allNodes)) {
            return new ArrayList<>();
        }
        if (StringUtils.isNotBlank(name)) {
            List<Long> topIds = allNodes.stream().map(IsfdBusinessScenariosVo::getTopId).toList();
            allNodes = baseMapper.selectByTopIds(topIds);
        }
        // map作为字典
        Map<Long, IsfdBusinessScenariosVo> nodeMap = new HashMap<>();
        for (IsfdBusinessScenariosVo node : allNodes) {
            nodeMap.put(node.getId(), node);
        }
        // 封装树
        List<IsfdBusinessScenariosVo> rootNodes = new ArrayList<>();
        for (IsfdBusinessScenariosVo node : allNodes) {
            Long parentId = node.getParentId();
            if (parentId == null || parentId == 0) {
                rootNodes.add(node);
            } else {
                IsfdBusinessScenariosVo parent = nodeMap.get(parentId);
                if (parent != null) {
                    parent.addChild(node);
                }
            }
        }
        return rootNodes;
    }

    @Override
    public IsfdBusinessScenariosVo queryById(Long id) {
        IsfdBusinessScenariosVo isfdBusinessScenariosVo = baseMapper.selectVoById(id);
        if (isfdBusinessScenariosVo != null) {
            SysUserVo sysUserVo = iSysUserService.selectUserById(isfdBusinessScenariosVo.getCreateBy());
            isfdBusinessScenariosVo.setCreateUserNickName(sysUserVo != null ? sysUserVo.getNickName() : null);
            if (isfdBusinessScenariosVo.getParentId() != 0) {
                IsfdBusinessScenariosVo parent = this.queryById(isfdBusinessScenariosVo.getParentId());
                isfdBusinessScenariosVo.setParentName(parent.getName());
            }
        }
        return isfdBusinessScenariosVo;
    }

    @Override
    public TableDataInfo<IsfdBusinessScenariosVo> queryPageList(IsfdBusinessScenariosQueryBo queryBo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(queryBo.getPageNum());
        pageQuery.setPageSize(queryBo.getPageSize());
        if (StringUtils.isNotBlank(queryBo.getIsAsc())) {
            pageQuery.setIsAsc(queryBo.getIsAsc());
        }
        LambdaQueryWrapper<IsfdBusinessScenarios> lqw = buildQueryWrapper(queryBo);
        Page<IsfdBusinessScenariosVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        result.getRecords().forEach(r -> {
            SysUserVo sysUserVo = iSysUserService.selectUserById(r.getCreateBy());
            r.setCreateUserNickName(sysUserVo != null ? sysUserVo.getNickName() : null);
            if (r.getParentId() != 0) {
                IsfdBusinessScenariosVo parent = this.queryById(r.getParentId());
                r.setParentName(parent.getName());
            }
        });
        return TableDataInfo.build(result);
    }

    @Override
    public List<IsfdBusinessScenariosVo> queryList(IsfdBusinessScenariosBo bo) {
        LambdaQueryWrapper<IsfdBusinessScenarios> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IsfdBusinessScenarios> buildQueryWrapper(IsfdBusinessScenariosQueryBo queryBo) {
        LambdaQueryWrapper<IsfdBusinessScenarios> lqw = Wrappers.lambdaQuery();
        if (queryBo.getId() != null) {
            lqw.and(lqw1 -> lqw1.eq(IsfdBusinessScenarios::getId, queryBo.getId())
                .or().eq(IsfdBusinessScenarios::getParentId, queryBo.getId()));
        }
        lqw.eq(queryBo.getParentId() != null, IsfdBusinessScenarios::getParentId, queryBo.getParentId());
        lqw.eq(queryBo.getTopId() != null, IsfdBusinessScenarios::getTopId, queryBo.getTopId());
        lqw.eq(queryBo.getType() != null, IsfdBusinessScenarios::getType, queryBo.getType());
        lqw.like(StringUtils.isNotBlank(queryBo.getName()), IsfdBusinessScenarios::getName, queryBo.getName());
        lqw.eq(StringUtils.isNotBlank(queryBo.getDescription()), IsfdBusinessScenarios::getDescription, queryBo.getDescription());
        if (queryBo.getStartCreateTime() != null && queryBo.getEndCreateTime() != null) {
            lqw.between(IsfdBusinessScenarios::getCreateTime, queryBo.getStartCreateTime(), queryBo.getEndCreateTime());
        }
        if (StringUtils.isBlank(queryBo.getCreateName())) {
            List<SysUserVo> sysUserVos = iSysUserService.selectUserVoByNickName(queryBo.getCreateName());
            List<Long> userIdList = sysUserVos.stream().map(SysUserVo::getUserId).toList();
            if (!CollectionUtils.isEmpty(userIdList)) {
                lqw.in(IsfdBusinessScenarios::getCreateBy, userIdList);
            }
        }
        lqw.orderByDesc(IsfdBusinessScenarios::getTopId)
            .orderByAsc(IsfdBusinessScenarios::getCreateTime);
        return lqw;
    }

    private LambdaQueryWrapper<IsfdBusinessScenarios> buildQueryWrapper(IsfdBusinessScenariosBo bo) {
        LambdaQueryWrapper<IsfdBusinessScenarios> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getParentId() != null, IsfdBusinessScenarios::getParentId, bo.getParentId());
        lqw.eq(bo.getTopId() != null, IsfdBusinessScenarios::getTopId, bo.getTopId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), IsfdBusinessScenarios::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getDescription()), IsfdBusinessScenarios::getDescription, bo.getDescription());
        lqw.eq(bo.getType() != null, IsfdBusinessScenarios::getType, bo.getType());
        lqw.orderByDesc(IsfdBusinessScenarios::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean insertByBo(IsfdBusinessScenariosBo bo) {
        if (IsfdBusinessScenariosTypeEnum.SYSTEM.getValue().equals(bo.getType()) && bo.getParentId() == 0) {
            throw new BaseException("创建业务系统，必须关联业务场景！");
        }
        IsfdBusinessScenarios add = MapstructUtils.convert(bo, IsfdBusinessScenarios.class);
        baseMapper.insert(add);
        if (IsfdBusinessScenariosTypeEnum.SYSTEM.getValue().equals(bo.getType())) {
            IsfdBusinessScenariosVo parent = this.queryById(bo.getParentId());
            add.setTopId(parent.getTopId());
        } else {
            add.setTopId(add.getId());
        }
        baseMapper.updateById(add);
        return Boolean.TRUE;
    }

    @Override
    public Boolean updateByBo(IsfdBusinessScenariosBo bo) {
        Long id = bo.getId();
        String name = bo.getName();
        IsfdBusinessScenariosBo queryBo = new IsfdBusinessScenariosBo();
        queryBo.setName(name);
        List<IsfdBusinessScenariosVo> oldList = this.queryList(queryBo);
        // 1. 名字幂等校验
        if (!CollectionUtils.isEmpty(oldList)) {
            for (IsfdBusinessScenariosVo old : oldList) {
                if (!old.getId().equals(bo.getId())) {
                    throw new BaseException("业务场景/业务系统 名称已经存在，请更换名称后重试！");
                }
            }
        }
        if(id.equals(bo.getParentId())){
            throw new BaseException("父节点不能选择自己！");
        }

        IsfdBusinessScenariosVo isfdBusinessScenariosVo = this.queryById(bo.getId());
        Integer type = isfdBusinessScenariosVo.getType();
        // 2. 校验是否type字段发生改变
        if (IsfdBusinessScenariosTypeEnum.SCENE.getValue().equals(type)) {
            List<IsfdBusinessScenariosVo> children = baseMapper.selectVoList(new LambdaQueryWrapper<IsfdBusinessScenarios>()
                .eq(IsfdBusinessScenarios::getParentId, id));
            if (!CollectionUtils.isEmpty(children)) {
                throw new BaseException("当前业务场景下已经关联业务系统，不能修改!");
            }
            // 把业务场景修改为业务系统
            if (IsfdBusinessScenariosTypeEnum.SYSTEM.getValue().equals(bo.getType())) {
                bo.setTopId(bo.getParentId());
            }
        } else {
            // 把业务系统修改为业务场景
            if (IsfdBusinessScenariosTypeEnum.SCENE.getValue().equals(bo.getType())) {
                bo.setTopId(id);
                bo.setParentId(0L);
            }
        }

        // 3.校验在模型中是否已经关联上
        IsfdBusinessDatabaseTypeEnum isfdBusinessDatabaseTypeEnum = IsfdBusinessDatabaseTypeEnum.SYSTEM;
        if (IsfdBusinessScenariosTypeEnum.SCENE.getValue().equals(type)) {
            isfdBusinessDatabaseTypeEnum = IsfdBusinessDatabaseTypeEnum.SCENE;
        }
        iIsfdDatabaseModelTreeService.checkIfNodeExist(isfdBusinessDatabaseTypeEnum, id, isfdBusinessScenariosVo.getName());

        IsfdBusinessScenarios update = MapstructUtils.convert(bo, IsfdBusinessScenarios.class);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional
    public Boolean deleteWithValidById(Long id) {
        IsfdBusinessScenariosVo isfdBusinessScenariosVo = baseMapper.selectVoById(id);
        if (isfdBusinessScenariosVo == null) {
            throw new BaseException("删除的数据不存在，请确认后重试！");
        }
        IsfdBusinessDatabaseTypeEnum isfdBusinessDatabaseTypeEnum = IsfdBusinessDatabaseTypeEnum.SYSTEM;
        Integer type = isfdBusinessScenariosVo.getType();
        if (IsfdBusinessScenariosTypeEnum.SCENE.getValue().equals(type)) {
            IsfdBusinessScenariosBo bo = new IsfdBusinessScenariosBo();
            bo.setParentId(id);
            List<IsfdBusinessScenariosVo> children = this.queryList(bo);
            if (!CollectionUtils.isEmpty(children)) {
                throw new BaseException("当前业务场景，存在关联的业务系统，请删除关联的业务系统后再删除当前业务场景！");
            }
            isfdBusinessDatabaseTypeEnum = IsfdBusinessDatabaseTypeEnum.SCENE;
        }
        iIsfdDatabaseModelTreeService.checkIfNodeExist(isfdBusinessDatabaseTypeEnum, id, isfdBusinessScenariosVo.getName());
        return baseMapper.deleteById(id) > 0;
    }
}
